﻿#pragma warning(disable:4005)
#include <drogon/HttpController.h>
#include "OCMain/Environment.h"
#include "OCMain/FileUtil.h"
#include "timer/GFSFetcher.h"
#include "OCServer/DocGenerate.h"
#include "apiDoc.h"

using namespace drogon;

ApiDocMehtodVec apiVec = {
	{
		"gfs/getLatest"
	},
	{
		"gfs/getList"
	},
	{
		"gfs/getFile",
		"v=Temperature_height_above_ground&t=20240530000000",
		{
			{true, "v","要素","Temperature_height_above_ground"},
			{true, "t","Time","20240530000000"},
			{true, "l","Level","10m"}
		}
	}
};

inline void setGZIp(HttpResponsePtr& resp)
{
	resp->addHeader("Content-Encoding", "gzip");
}

class WeatherService : public HttpController<WeatherService>
{
public:
	METHOD_LIST_BEGIN
		METHOD_ADD(WeatherService::home, "", Get);
		METHOD_ADD(MyDoc::doc, "/doc?query={}", Get);
		METHOD_ADD(WeatherService::getFile, "gfs/getFile?time={time}&var={var}&level={level}", Get);
		METHOD_ADD(WeatherService::getTimeList, "gfs/getTimeList?startTime={startTime}&endTime={endTime}", Get);
	METHOD_LIST_END
protected:
	void home(const HttpRequestPtr& req,
		std::function<void(const HttpResponsePtr&)>&& callback)
	{
		auto resp = HttpResponse::newHttpResponse();

		static String docApi;
		if (docApi.empty())
		{
			DocGenerate doc;
			docApi = doc.toMarkdown(apiVec, "WeatherService");
		}
		resp->setBody(docApi);

		callback(resp);
	}

	void doc(const HttpRequestPtr& req,
		std::function<void(const HttpResponsePtr&)>&& callback,
		String queryapi)
	{
		String docClass = "WeatherService";
		if (queryapi == "")
		{
			auto resp = drogon::HttpResponse::newRedirectionResponse("/swagger/index.html?s=" + docClass);
			callback(resp);
		}
		else
		{
			auto resp = HttpResponse::newNotFoundResponse();
			callback(resp);
		}
	}

	void getFile(const HttpRequestPtr& req,
		std::function<void(const HttpResponsePtr&)>&& callback,
		String time,String var,String level)
	{
		auto resp = HttpResponse::newHttpResponse();

		if (time.empty() || var.empty())
		{
			resp->setStatusCode(k404NotFound);
		}
		else
		{
			String fileName = Singleton(GFSFetcher).getFile(time, var, level);
			String bin = FileUtil::getFileBinary(fileName);
			if (!bin.empty())
			{
				resp = drogon::HttpResponse::newFileResponse((const unsigned char*)bin.data(), bin.length(),
					var + "_" + time + ".bin",
					CT_APPLICATION_OCTET_STREAM);
				setGZIp(resp);
			}
			else
			{
				resp->setStatusCode(k404NotFound);
			}
		}

		callback(resp);
	}

	void getTimeList(const HttpRequestPtr& req,
		std::function<void(const HttpResponsePtr&)>&& callback,
		String startTime, String endTime)
	{
		auto resp = HttpResponse::newHttpResponse();
		auto timeVec = Singleton(GFSFetcher).db_query(startTime, endTime);
		Json::Value data;

		if (timeVec.empty())
		{
			resp->setBody("[]");
		}
		else
		{
			Json::Value value;
			for (const auto& time : timeVec)
			{
				value.append(time);
			}
			resp->setBody(value.toStyledString());
		}

		callback(resp);
	}
};